#ifndef DPV_DEVICE_HPP
#define DPV_DEVICE_HPP

#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>

#include <sylvan.h>
#include <sylvan_obj.hpp>

using namespace sylvan;

/**
 * This file contains most of entities in the network, including:
 * Rule (flow rule), Port, Device and the Trie of rules owned by each device.
 */

using namespace std;

class Port;
class Device;

/**
 * Rule, Port and Device are unique object, which are only referred by pointer.
 *
 * Each device has an inner structure Trie, which should not be accessed in any other way.
 */
struct Rule {
    Device* device;
    long dstIp;
    int priority;
    BDD hit, nMatch;
    Port* port;
};

struct Port {
    string name;
    Device* device;
    unordered_set<Port*> peers;
};

class Trie {
    struct TrieNode {
        vector<Rule*> rules;
        TrieNode *l, *r;
        TrieNode* getNext(int flag);
        TrieNode();
    };
public:
    Trie();
    void explore(vector<Rule*> *ret, TrieNode * const t);
    vector<Rule*> addAndGetAllRulesUntil(Rule* rule);
private:
    TrieNode* root;
};

class Device {
public:
    static int cnt;
    const int uid;
    string name;
    Device(const string &name);
    Port* addPortByName(const string &name);
    Port* getPortByName(const string &name);
    vector<Rule*> addAndGetAllRulesUntil(Rule *rule);
private:
    Trie rules;
    unordered_map<string, Port*> nameToPort;
};

#endif //DPV_DEVICE_HPP
